package com.kreao.korean.service;

import com.kreao.korean.dto.StudyRequest;
import com.kreao.korean.dto.StudyStatistics;
import com.kreao.korean.entity.StudyRecord;
import com.kreao.korean.entity.User;
import com.kreao.korean.entity.Word;
import com.kreao.korean.repository.StudyRecordRepository;
import com.kreao.korean.repository.UserRepository;
import com.kreao.korean.repository.WordRepository;
import com.kreao.korean.service.interfaces.StudyService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service("studyServiceImpl")
@RequiredArgsConstructor
@Transactional
public class StudyServiceImpl implements StudyService {
    
    private final StudyRecordRepository studyRecordRepository;
    private final WordRepository wordRepository;
    private final UserRepository userRepository;
    
    public StudyRecord recordStudy(StudyRequest request, Long userId) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        Word word = wordRepository.findById(request.getWordId())
            .orElseThrow(() -> new RuntimeException("单词不存在"));
        
        if (!word.getUser().getId().equals(userId)) {
            throw new RuntimeException("无权限操作此单词");
        }
        
        // 创建学习记录
        StudyRecord studyRecord = new StudyRecord();
        studyRecord.setUser(user);
        studyRecord.setWord(word);
        studyRecord.setStudyType(request.getStudyType());
        studyRecord.setIsCorrect(request.getIsCorrect());
        studyRecord.setResponseTime(request.getResponseTime());
        studyRecord.setUserAnswer(request.getUserAnswer());
        studyRecord.setCorrectAnswer(request.getCorrectAnswer());
        studyRecord.setNotes(request.getNotes());
        
        StudyRecord savedRecord = studyRecordRepository.save(studyRecord);
        
        // 更新单词统计
        updateWordStatistics(word, request.getIsCorrect());
        
        // 更新用户统计
        updateUserStatistics(user);
        
        return savedRecord;
    }
    
    private void updateWordStatistics(Word word, Boolean isCorrect) {
        word.setReviewCount(word.getReviewCount() + 1);
        
        if (isCorrect) {
            word.setCorrectCount(word.getCorrectCount() + 1);
        } else {
            word.setWrongCount(word.getWrongCount() + 1);
        }
        
        // 计算正确率
        double accuracy = (double) word.getCorrectCount() / word.getReviewCount();
        word.setAccuracy(accuracy);
        
        // 更新复习时间
        word.setLastReviewTime(LocalDateTime.now());
        
        // 根据正确率调整下次复习时间
        int daysToAdd = calculateNextReviewDays(accuracy, word.getReviewCount());
        word.setNextReviewTime(LocalDateTime.now().plusDays(daysToAdd));
        
        wordRepository.save(word);
    }
    
    private int calculateNextReviewDays(double accuracy, int reviewCount) {
        if (accuracy >= 0.9) {
            return Math.min(30, reviewCount * 2); // 正确率高，延长复习间隔
        } else if (accuracy >= 0.7) {
            return Math.min(7, reviewCount); // 中等正确率
        } else {
            return 1; // 正确率低，明天再复习
        }
    }
    
    private void updateUserStatistics(User user) {
        // 更新学习天数
        LocalDateTime today = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        if (user.getLastStudyTime() == null || user.getLastStudyTime().isBefore(today)) {
            user.setStudyDays(user.getStudyDays() + 1);
        }
        user.setLastStudyTime(LocalDateTime.now());
        
        // 更新平均正确率
        Double averageAccuracy = wordRepository.getAverageAccuracyByUserId(user.getId());
        if (averageAccuracy != null) {
            user.setAccuracy(averageAccuracy);
        }
        
        userRepository.save(user);
    }
    
    public StudyStatistics getStudyStatistics(Long userId) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        LocalDateTime startOfToday = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime startOfMonth = LocalDateTime.now().minusDays(30);
        
        StudyStatistics statistics = new StudyStatistics();
        
        // 基础统计
        statistics.setTotalStudyCount(studyRecordRepository.countByUserIdAndStudyTimeAfter(userId, LocalDateTime.now().minusYears(1)));
        statistics.setTodayStudyCount(studyRecordRepository.countByUserIdAndStudyTimeAfter(userId, startOfToday));
        
        Long correctCount = studyRecordRepository.countCorrectAnswersByUserIdAndDate(userId, LocalDateTime.now().minusYears(1));
        Long totalCount = statistics.getTotalStudyCount();
        statistics.setAverageAccuracy(totalCount > 0 ? (double) correctCount / totalCount : 0.0);
        
        statistics.setAverageResponseTime(studyRecordRepository.getAverageResponseTime(userId, startOfMonth));
        statistics.setStudyDays((long) user.getStudyDays());
        statistics.setTotalWords((long) user.getTotalWords());
        
        // 收藏单词数
        Long favoriteCount = wordRepository.findByUserIdAndIsFavorite(userId, true, null).getTotalElements();
        statistics.setFavoriteWords(favoriteCount);
        
        // 每日学习统计
        List<Object[]> dailyData = studyRecordRepository.getDailyStudyStatistics(userId, startOfMonth);
        List<StudyStatistics.DailyStudyData> dailyStudyData = dailyData.stream()
            .map(data -> new StudyStatistics.DailyStudyData(
                ((java.sql.Date) data[0]).toLocalDate(),
                ((Number) data[1]).longValue()
            ))
            .collect(Collectors.toList());
        statistics.setDailyStudyData(dailyStudyData);
        
        // 学习类型统计
        List<Object[]> studyTypeData = studyRecordRepository.getStudyTypeStatistics(userId);
        Map<String, Long> studyTypeStats = new HashMap<>();
        for (Object[] data : studyTypeData) {
            studyTypeStats.put(data[0].toString(), ((Number) data[1]).longValue());
        }
        statistics.setStudyTypeStatistics(studyTypeStats);
        
        return statistics;
    }
    
    @Override
    public StudyStatistics getRecentStudyData(Long userId, int days) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        LocalDateTime startDate = LocalDateTime.now().minusDays(days);
        LocalDateTime endDate = LocalDateTime.now();
        
        StudyStatistics statistics = new StudyStatistics();
        
        // 获取指定天数内的学习统计
        Long totalCount = studyRecordRepository.countByUserIdAndStudyTimeBetween(userId, startDate, endDate);
        Long correctCount = studyRecordRepository.countCorrectAnswersByUserIdAndDateRange(userId, startDate, endDate);
        
        statistics.setTotalStudyCount(totalCount);
        statistics.setAverageAccuracy(totalCount > 0 ? (double) correctCount / totalCount : 0.0);
        statistics.setStudyDays((long) user.getStudyDays());
        
        // 每日学习统计
        List<Object[]> dailyData = studyRecordRepository.getDailyStudyStatistics(userId, startDate);
        List<StudyStatistics.DailyStudyData> dailyStudyData = dailyData.stream()
            .map(data -> new StudyStatistics.DailyStudyData(
                ((java.sql.Date) data[0]).toLocalDate(),
                ((Number) data[1]).longValue()
            ))
            .collect(Collectors.toList());
        statistics.setDailyStudyData(dailyStudyData);
        
        return statistics;
    }
} 